package com.goldplusgold.tradedelay.app.market;

import android.text.TextUtils;

import com.goldplusgold.support.lib.utils.StringConvertNumber;
import com.goldplusgold.network.lib.http.netty.ChannelManager;
import com.goldplusgold.network.lib.http.protobuf.Market;
import com.goldplusgold.tradedelay.app.market.pojo.CMinute;
import com.goldplusgold.tradedelay.app.market.pojo.StickData;
import com.goldplusgold.tradedelay.app.market.widget.chartutil.IndexParseUtil;
import com.goldplusgold.tradedelay.app.my.networkservice.MyService;
import com.goldplusgold.tradedelay.app.my.account.UserInfo;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/7/3.
 */

public class MarketManager {

    private static MarketManager manager;
    private List<StickData> stickList = new ArrayList<>();
    private List<CMinute> minuteList = new ArrayList<>();
    private long volumeTotal = 0;
    private double amountTotal = 0;
    private Market.InstType mInstType;
    private String lastSettle;
    StickReceiver stickReceiver;
    MinuteReceiver minuteReceiver;

    private MarketManager() {
    }

    public static MarketManager getInstance() {
        if (manager == null) {
            synchronized (MarketManager.class) {
                if (manager == null) {
                    manager = new MarketManager();
                }
            }
        }
        return manager;
    }


    public void setStickReceiver(StickReceiver stickReceiver) {
        synchronized (MarketManager.class){
            this.stickReceiver = stickReceiver;
        }

    }

    public void setMinuteReceiver(MinuteReceiver minuteReceiver) {
        synchronized (MarketManager.class){
            this.minuteReceiver = minuteReceiver;
        }
    }

    public void sendRequestMsg(Market.InstType instType) {
        sendRequestMsg(instType,null);
    }

    public void sendRequestMsg(Market.InstType instType, Market.Category category) {
        this.mInstType = instType;
        UserInfo userInfo = MyService.getInstance().getmUserInfo();
        String userName = "";
        if (userInfo != null) {
            userName = userInfo.getUserName();
        }
        Market.Identification.Builder builder = Market.Identification.newBuilder();
        if(category != null){
            builder.setCategory(category);
        } else {
            builder.setCategory(Market.Category.QUOTEMINPAGE);
        }
        if (!TextUtils.isEmpty(userName)) {
            builder.setGoldExpertNo(userName);
        }
        builder.setInstType(instType);
        builder.setIndex(0);
        Market.Identification identification = builder.build();
        Market.Response response = Market.Response.newBuilder().setIdentification(identification).build();
        ChannelManager.sendMessage(0, response, 100175);
    }

    private void handleData(Market.QuoteKline quoteKline){
        if (quoteKline == null) {
            return;
        }
        int size = quoteKline.getAmountList().size();
        StickData stickData;
        stickList.clear();
        for (int i = 0; i < size; i++) {
            double k_max = 0;
            double k_min = Double.MAX_VALUE;
            double c_max = 0;
            int id = (int) quoteKline.getId(i);
            double high = StringConvertNumber.parseDouble(quoteKline.getHigh(i));
            double low = StringConvertNumber.parseDouble(quoteKline.getLow(i));
            long volume = quoteKline.getVolume(i);
            stickData = new StickData();
            stickData.setId(id);
            stickData.setTime(StringConvertNumber.parseInt(String.valueOf(quoteKline.getId(i)).substring(0, String.valueOf(quoteKline.getId(i)).length() - 3)));
            stickData.setDate(quoteKline.getTime(i));
            stickData.setOpen(StringConvertNumber.parseDouble(quoteKline.getOpen(i)));
            stickData.setClose(StringConvertNumber.parseDouble(quoteKline.getClose(i)));
            stickData.setHigh(StringConvertNumber.parseDouble(quoteKline.getHigh(i)));
            stickData.setLow(StringConvertNumber.parseDouble(quoteKline.getLow(i)));
            stickData.setMoney(StringConvertNumber.parseDouble(quoteKline.getAmount(i)));
            stickData.setCount(quoteKline.getVolume(i));
            stickList.add(stickData);
            int to_index = i+1;
            if(to_index >= size){
                to_index = size;
            }
            double csma5 = 0;
            double sma5 = 0;
            double csma10 = 0;
            double sma10 = 0;
            double csma20 = 0;
            double sma20 = 0;
            if ( i >= IndexParseUtil.START_SMA5 ) {
                csma5 = IndexParseUtil.getCountSma(stickList.subList(to_index -IndexParseUtil.START_SMA5 -1, to_index));
                sma5 = IndexParseUtil.getCloseSma(stickList.subList(to_index -IndexParseUtil.START_SMA5 -1, to_index));
                //量的SMA5
                stickList.get(i).setCountSma5(csma5);
                //K线的SMA5
                stickList.get(i).setSma5(sma5);
            }
            //第10日开始计算10日均线
            if (i >= IndexParseUtil.START_SMA10 ) {
                csma10 = IndexParseUtil.getCountSma(stickList.subList(to_index - IndexParseUtil.START_SMA10 - 1, to_index));
                sma10 = IndexParseUtil.getCloseSma(stickList.subList(to_index - IndexParseUtil.START_SMA10 -1, to_index));
                //量的SMA10
                stickList.get(i).setCountSma10(csma10);
                //K线的SMA10
                stickList.get(i).setSma10(sma10);
            }
            if (i >= IndexParseUtil.START_SMA20 ) {
                csma20 = IndexParseUtil.getCountSma(stickList.subList(to_index - IndexParseUtil.START_SMA20 -1, to_index ));
                sma20 = IndexParseUtil.getCloseSma(stickList.subList(to_index - IndexParseUtil.START_SMA20 -1, to_index ));
                //K线的SMA20
                stickList.get(i).setCountSma20(csma20);
                stickList.get(i).setSma20(sma20);
            }
            k_max = high > k_max? high:k_max;
            k_max = sma5 > k_max? sma5:k_max;
            k_max = sma10 > k_max? sma10:k_max;
            k_max = sma20 > k_max? sma20:k_max;
            k_min = low < k_min?low:k_min;
            if(sma5 != 0){
                k_min = sma5 < k_min?sma5:k_min;
            }
            if(sma10 != 0){
                k_min = sma10 < k_min?sma10:k_min;
            }
            if(sma20 != 0){
                k_min = sma20 < k_min?sma20:k_min;
            }
            stickList.get(i).setK_lineYmax(k_max);
            stickList.get(i).setK_lineYmin(k_min);
            c_max = volume > c_max? volume:c_max;
            c_max = csma5 > c_max? csma5:c_max;
            c_max = csma10 > c_max? csma10:c_max;
            c_max = csma20 > c_max? csma20:c_max;
            stickList.get(i).setC_lineYmax(c_max);
        }
        refreshData(new ArrayList<StickData>(stickList));
    }

    private void fastRefreshData(Market.QuoteKline quoteKline){
        if (quoteKline == null) {
            return;
        }
        List<StickData> datas = new ArrayList<>();
        int size = quoteKline.getAmountList().size();
        int start_index = size - 120;
        StickData stickData;
        int sma_index_sub = start_index;
        int j = -1;
        for (int i = start_index; i < size; i++) {
            double k_max = 0;
            double k_min = Double.MAX_VALUE;
            double c_max = 0;
            double high = StringConvertNumber.parseDouble(quoteKline.getHigh(i));
            double low = StringConvertNumber.parseDouble(quoteKline.getLow(i));
            long volume = quoteKline.getVolume(i);
            int id = (int) quoteKline.getId(i);
            stickData = new StickData();
            stickData.setId(id);
            stickData.setTime(StringConvertNumber.parseInt(String.valueOf(quoteKline.getId(i)).substring(0, String.valueOf(quoteKline.getId(i)).length() - 3)));
            stickData.setDate(quoteKline.getTime(i));
            stickData.setOpen(StringConvertNumber.parseDouble(quoteKline.getOpen(i)));
            stickData.setClose(StringConvertNumber.parseDouble(quoteKline.getClose(i)));
            stickData.setHigh(StringConvertNumber.parseDouble(quoteKline.getHigh(i)));
            stickData.setLow(StringConvertNumber.parseDouble(quoteKline.getLow(i)));
            stickData.setMoney(StringConvertNumber.parseDouble(quoteKline.getAmount(i)));
            stickData.setCount(quoteKline.getVolume(i));
            datas.add(stickData);
            j++;
            int to_index = j;
            double csma5 = 0;
            double sma5 = 0;
            double csma10 = 0;
            double sma10 = 0;
            double csma20 = 0;
            double sma20 = 0;
            if ( i >= IndexParseUtil.START_SMA5 + sma_index_sub ) {
                csma5 = IndexParseUtil.getCountSma(datas.subList(to_index -IndexParseUtil.START_SMA5 , to_index +1));
                sma5 = IndexParseUtil.getCloseSma(datas.subList(to_index -IndexParseUtil.START_SMA5 , to_index +1));
                //量的SMA5
                datas.get(j).setCountSma5(csma5);
                //K线的SMA5
                datas.get(j).setSma5(sma5);
            }
            //第10日开始计算10日均线
            if (i >= IndexParseUtil.START_SMA10 + sma_index_sub) {
                csma10 = IndexParseUtil.getCountSma(datas.subList(to_index - IndexParseUtil.START_SMA10 , to_index+1));
                sma10 = IndexParseUtil.getCloseSma(datas.subList(to_index - IndexParseUtil.START_SMA10 , to_index+1));
                //量的SMA10
                datas.get(j).setCountSma10(csma10);
                //K线的SMA10
                datas.get(j).setSma10(sma10);
            }
            if (i >= IndexParseUtil.START_SMA20 + sma_index_sub ) {
                csma20 = IndexParseUtil.getCountSma(datas.subList(to_index - IndexParseUtil.START_SMA20 , to_index +1));
                sma20 = IndexParseUtil.getCloseSma(datas.subList(to_index - IndexParseUtil.START_SMA20 , to_index +1));
                //K线的SMA20
                datas.get(j).setCountSma20(csma20);
                datas.get(j).setSma20(sma20);
            }
            k_max = high > k_max? high:k_max;
            k_max = sma5 > k_max? sma5:k_max;
            k_max = sma10 > k_max? sma10:k_max;
            k_max = sma20 > k_max? sma20:k_max;
            k_min = low < k_min?low:k_min;
            if(sma5 != 0){
                k_min = sma5 < k_min?sma5:k_min;
            }
            if(sma10 != 0){
                k_min = sma10 < k_min?sma10:k_min;
            }
            if(sma20 != 0){
                k_min = sma20 < k_min?sma20:k_min;
            }
            datas.get(j).setK_lineYmax(k_max);
            datas.get(j).setK_lineYmin(k_min);
            c_max = volume > c_max? volume:c_max;
            c_max = csma5 > c_max? csma5:c_max;
            c_max = csma10 > c_max? csma10:c_max;
            c_max = csma20 > c_max? csma20:c_max;
            datas.get(j).setC_lineYmax(c_max);
        }
        refreshData(datas);
        handleData(quoteKline);
    }

    private void refreshData(List<StickData> datas) {
        synchronized (MarketManager.class){
            if(this.stickReceiver != null){
                this.stickReceiver.onReceive(new ArrayList<StickData>(datas));
            }
        }
    }

    public synchronized void  parseStickData(Market.QuoteKline quoteKline) {
        if (quoteKline == null) {
            return;
        }
        int size = quoteKline.getAmountList().size();
        StickData stickData;
        if(size == 1){
            int i = 0;
            int id = (int) quoteKline.getId(i);
            double high = StringConvertNumber.parseDouble(quoteKline.getHigh(i));
            double low = StringConvertNumber.parseDouble(quoteKline.getLow(i));
            long volume = quoteKline.getVolume(i);
            double k_max = 0;
            double k_min = Double.MAX_VALUE;
            double c_max = 0;
            stickData = new StickData();
            stickData.setId(id);
            stickData.setTime(StringConvertNumber.parseInt(String.valueOf(quoteKline.getId(i)).substring(0, String.valueOf(quoteKline.getId(i)).length() - 3)));
            stickData.setDate(quoteKline.getTime(i));
            stickData.setOpen(StringConvertNumber.parseDouble(quoteKline.getOpen(i)));
            stickData.setClose(StringConvertNumber.parseDouble(quoteKline.getClose(i)));
            stickData.setHigh(high);
            stickData.setLow(low);
            stickData.setMoney(StringConvertNumber.parseDouble(quoteKline.getAmount(i)));
            stickData.setCount(quoteKline.getVolume(i));
            int count = stickList.size();
            if(stickList.get(count -1).getId() == id){
                stickList.remove(count - 1);
            }
            stickList.add(stickData);
            count = stickList.size();
            int to_index = count;
            //量的SMA5
            double csma5 = IndexParseUtil.getCountSma(stickList.subList(to_index -IndexParseUtil.START_SMA5 -1, to_index));
            double sma5 = IndexParseUtil.getCloseSma(stickList.subList(to_index -IndexParseUtil.START_SMA5 -1, to_index));
            double csma10 = IndexParseUtil.getCountSma(stickList.subList(to_index - IndexParseUtil.START_SMA10 - 1, to_index));
            double sma10 = IndexParseUtil.getCloseSma(stickList.subList(to_index - IndexParseUtil.START_SMA10 -1, to_index));
            double csma20 = IndexParseUtil.getCountSma(stickList.subList(to_index - IndexParseUtil.START_SMA20 -1, to_index ));
            double sma20 = IndexParseUtil.getCloseSma(stickList.subList(to_index - IndexParseUtil.START_SMA20 -1, to_index ));
            stickList.get(count -1).setCountSma5(csma5);
            //K线的SMA5
            stickList.get(count -1).setSma5(sma5);
            //第10日开始计算10日均线
            //量的SMA10
            stickList.get(count -1).setCountSma10(csma10);
            //K线的SMA10
            stickList.get(count -1).setSma10(sma10);
            //K线的SMA20
            stickList.get(count -1).setCountSma20(csma20);
            stickList.get(count -1).setSma20(sma20);

            k_max = high > k_max? high:k_max;
            k_max = sma5 > k_max? sma5:k_max;
            k_max = sma10 > k_max? sma10:k_max;
            k_max = sma20 > k_max? sma20:k_max;
            k_min = low < k_min?low:k_min;
            k_min = sma5 < k_min?sma5:k_min;
            k_min = sma10 < k_min?sma10:k_min;
            k_min = sma20 < k_min?sma20:k_min;
            stickList.get(count -1).setK_lineYmax(k_max);
            stickList.get(count -1).setK_lineYmin(k_min);
            c_max = volume > c_max? volume:c_max;
            c_max = csma5 > c_max? csma5:c_max;
            c_max = csma10 > c_max? csma10:c_max;
            c_max = csma20 > c_max? csma20:c_max;
            stickList.get(count -1).setC_lineYmax(c_max);
            refreshData(new ArrayList<StickData>(stickList));
        } else{
            if(size > 300){
                fastRefreshData(quoteKline);
            } else {
                handleData(quoteKline);
            }
        }
    }

    public synchronized void parseMinuteData(Market.QuoteMin quoteMin) {
        lastSettle = quoteMin.getLastSettle(0);
        int size = quoteMin.getPriceList().size();
        CMinute cMinute;
        if (size == 0) {
            return;
        }
        if (size == 1) {
            int i = 0;
            int id = (int) quoteMin.getId(i);
            cMinute = new CMinute();
            long volume = quoteMin.getVolume(i);
            double price = StringConvertNumber.parseDouble(quoteMin.getPrice(i));
            double amount = StringConvertNumber.parseDouble(quoteMin.getAmount(i));
            volumeTotal = volume + volumeTotal;
            amountTotal = amount + amountTotal;
            double average = 0.0;
            switch (mInstType) {
                case AG_TD:
                    average = amountTotal / volumeTotal;
                    break;
                case AU_TD:
                    average = amountTotal / (volumeTotal * 1000);
                    break;
                case MAU_TD:
                    average = amountTotal / (volumeTotal * 100);
                    break;
            }
            cMinute.setId(id);
            cMinute.setAverage(average);
            cMinute.setCount(volume);
            cMinute.setPrice(price);
            cMinute.setRate(quoteMin.getUpDownRate(i).substring(0, quoteMin.getUpDownRate(i).length() - 1));
            cMinute.setTime(Integer.parseInt(String.valueOf(quoteMin.getId(i)).substring(0, String.valueOf(quoteMin.getId(i)).length() - 3)));
            cMinute.setMoney(amount);
            cMinute.setMoney(amount);
            int count = minuteList.size();
            if (minuteList.get(count - 1).getId() == id) {
                minuteList.remove(count - 1);
            }
            minuteList.add(cMinute);
        } else {
            minuteList.clear();
            volumeTotal = 0;
            amountTotal = 0;
            for (int i = 0; i < size; i++) {
                int id = (int) quoteMin.getId(i);
                cMinute = new CMinute();
                long volume = quoteMin.getVolume(i);
                double price = StringConvertNumber.parseDouble(quoteMin.getPrice(i));
                double amount = StringConvertNumber.parseDouble(quoteMin.getAmount(i));
                volumeTotal = volume + volumeTotal;
                amountTotal = amount + amountTotal;
                double average = 0.0;
                switch (mInstType) {
                    case AG_TD:
                        average = amountTotal / volumeTotal;
                        break;
                    case AU_TD:
                        average = amountTotal / (volumeTotal * 1000);
                        break;
                    case MAU_TD:
                        average = amountTotal / (volumeTotal * 100);
                        break;
                }
                cMinute.setId(id);
                cMinute.setAverage(average);
                cMinute.setCount(volume);
                cMinute.setPrice(price);
                cMinute.setRate(quoteMin.getUpDownRate(i).substring(0, quoteMin.getUpDownRate(i).length() - 1));
                cMinute.setTime(Integer.parseInt(String.valueOf(quoteMin.getId(i)).substring(0, String.valueOf(quoteMin.getId(i)).length() - 3)));
                cMinute.setMoney(amount);
                cMinute.setMoney(amount);
                minuteList.add(cMinute);
            }
        }

        synchronized (MarketManager.class){
            if(this.minuteReceiver != null){
                minuteReceiver.onReceive(new ArrayList<CMinute>(minuteList),lastSettle);
            }
        }
    }

    public interface StickReceiver{
        void onReceive(List<StickData> list);
    }

    public interface MinuteReceiver{
        void onReceive(List<CMinute> list ,String lastSettle);
    }
}
